package com.chenjun.TxtFileCutter;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class FileCutterHandler
{
	/**
	 * @param fullPathAndName
	 *            文件全路径名
	 * @param count
	 *            份数
	 */
	public void execute(String fullPathAndName, int count)
	{
		this.cutAndSaveFile(new File(fullPathAndName), count);
	}

	/**
	 * 文件，切割成的段数, 举例：如果原始文件是7行 ，切割成三段，则三个文件行数分别为2,2,3
	 * 
	 * @param bigFile
	 *            大文件对象
	 */
	private void cutAndSaveFile(File bigFile, int n)
	{
		BigTxt bigTxt = this.readFile(bigFile);
		n = this.checkCutParam(bigTxt, n);
		for (int i = 0; i < n; i++)
		{
			// windows和Linux/Unix的文件路径分割符号不一样 ，统一写成File.separatorChar
			String smallFileName = bigTxt.getFileAbsPath() + File.separatorChar + this.dateFormat(new Date()) + "-" + i + ".txt";
			File smallFile = new File(smallFileName);
			if (!smallFile.exists())
			{
				this.createAndWrite(bigTxt, smallFile, i, n);
				System.out.println("--------------------------------------------------------------");
			}
		}
		// 切割完毕之后在系统资源管理器中打开路径
		try
		{
			String osName = System.getProperty("os.name");
			if (osName != null)
			{
				if (osName.contains("Mac"))
				{
					Runtime.getRuntime().exec("open " + bigTxt.getFileAbsPath());
				}
				else if (osName.contains("Windows") || osName.contains("windows"))
				{
					Runtime.getRuntime().exec("cmd /c start " + bigTxt.getFileAbsPath());
				}
				else
				{
					System.out.println("--------------切割小文件输出路径--------------:" + bigTxt.getFileAbsPath());
				}
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	private int checkCutParam(BigTxt bigTxt, int n)
	{
		// 如果要分的份数比文件总行数更多
		if (n > bigTxt.getTotalLineNumber())
		{
			n = 1;
		}
		return n;
	}

	private synchronized String dateFormat(Date date)
	{
		String result = "";
		SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-HH-mm-ss");
		result = sdf.format(date);
		return result;
	}

	/**
	 * 创建切割后的小文件并且进行读取
	 * 
	 * @param bigTxt
	 *            按行建模的大文件
	 * @param smallFile
	 *            小文件
	 * @param n
	 *            循环变量
	 * @param n
	 *            要切割成的分数
	 * 
	 */
	private void createAndWrite(BigTxt bigTxt, File smallFile, int i, int n)
	{
		// 计算每个小文件的行数
		int smallFileLineNumber = bigTxt.getTotalLineNumber() / n;

		// 设置当前上下文游标区间
		int fromIndex = smallFileLineNumber * i;
		int toIndex;
		// 核心算法
		if (i == n - 1) // 如果是最后一段分割
		{
			if (bigTxt.getTotalLineNumber() - fromIndex > smallFileLineNumber)
			{
				toIndex = bigTxt.getTotalLineNumber();
			}
			else
			{
				toIndex = smallFileLineNumber * (i + 1);
			}
		}
		else
		{
			toIndex = smallFileLineNumber * (i + 1);
		}
		// 文件写入buffer流
		BufferedWriter bufferedWriter = null;
		try
		{
			smallFile.createNewFile();
			System.out.println("文件" + smallFile.getAbsolutePath() + "创建成功");
			List<String> txtLineList = bigTxt.getLineList();
			List<String> smallFileLines = txtLineList.subList(fromIndex, toIndex);
			System.out.println("文件" + smallFile.getAbsolutePath() + "切割成功...准备开始写入文件...");
			// 写入文件
			bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(smallFile, true))); // 追加的方法
			for (String s : smallFileLines)
			{
				bufferedWriter.write(s);
				bufferedWriter.write("\r\n");
			}
			System.out.println("文件" + smallFile.getAbsolutePath() + "写入完毕...");
		}
		catch (IOException e)
		{
			System.err.println(smallFile.getName() + "文件创建失败");
		}
		finally
		{
			try
			{
				bufferedWriter.close();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
	}

	/**
	 * 读取文件，返回BigTxt对象
	 * 
	 * @param file
	 * @return
	 */
	public BigTxt readFile(File file)
	{
		BigTxt bigTxt = new BigTxt();
		FileReader fileReader = null;
		BufferedReader bufferedReader = null;
		List<String> txtFileLineList = new ArrayList<String>();

		try
		{
			fileReader = new FileReader(file);
			bufferedReader = new BufferedReader(fileReader);
			// 存储绝对路径
			String absPath = file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(File.separatorChar));
			bigTxt.setFileAbsPath(absPath);
			System.out.println("大文件和输出文件的绝对路径：" + absPath);
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		String temp = "";
		try
		{
			temp = bufferedReader.readLine();

			while (temp != null)
			{
				txtFileLineList.add(temp);
				temp = bufferedReader.readLine();
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		finally
		{
			try
			{
				// 一定要记得关闭哦
				bufferedReader.close();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		System.out.println("总行数" + txtFileLineList.size());
		bigTxt.setLineList(txtFileLineList);
		return bigTxt;
	}

}

class BigTxt
{
	private String fileAbsPath; // 文件绝对路径
	private List<String> lineList; // 用list的一个元素存储文件的一个行
	private int totalLineNumber; // 总行数

	public String getFileAbsPath()
	{
		return fileAbsPath;
	}

	public void setFileAbsPath(String fileAbsPath)
	{
		this.fileAbsPath = fileAbsPath;
	}

	public int getTotalLineNumber()
	{
		return this.lineList.size();
	}

	public List<String> getLineList()
	{
		return lineList;
	}

	public void setLineList(List<String> lineList)
	{
		this.lineList = lineList;
	}
}
